package seismosurfer.domain;

import java.net.MalformedURLException;
import java.net.URL;

import oracle.ord.im.OrdHttpUploadFile;
import seismosurfer.data.DocumentData;
import seismosurfer.database.DocumentDAO;
import seismosurfer.database.QuakeDAO;
import seismosurfer.util.Registry;

/**
 * A document representation. Provides all the functionality
 * that is associated with a document, which is a file that
 * contains information for an earthquake.
 *
 */
public class Document extends DomainObject {

    public static final String MISSING_DESCRIPTION = "Description was not submitted.";

    public static final String MISSING_INFO = "Info was not submitted.";

    public static final String MISSING_URL = "URL was not submitted.";

    public static final String MISSING_QUAKEID = "Quake id is missing.";

    public static final String UNKNOWN_QUAKE = "Quake is unknown.";

    public static final String MALFORMED_URL = "URL is not in the right form.";

    public static final String ZERO_LENGTH_DOC = "Document is empty.";

    public static final String MISSING_DOC_NAME = "Document is missing.";

    private URL url = null;

    private DocumentData docData = (DocumentData) data;
    
    /**
     * Created a document object, given its data.
     *  
     * @param dd the DocumentData that holds the data
     *           of a document
     */
    public Document(DocumentData dd) {
        super(dd);
    }
    
    /**
     * A template method implementation that 
     * represents an upload. Implements some common
     * functionality, but most of its methods are
     * abstract and the implementations are
     * provided by specific types of uploads.  
     *
     */
    protected abstract class Uploader {

        void validateFields() {
            // quakeid
            boolean failed = failIfNullOrBlank(String.valueOf(docData
                    .getQuakeID()), QUAKEID, MISSING_QUAKEID);

            if (!failed) {
                fail(QuakeDAO.findQuake(docData.getQuakeID()) == null, QUAKEID,
                        UNKNOWN_QUAKE);
            }

            // description
            fail(docData.getDescription() == null, DESCRIPTION,
                    MISSING_DESCRIPTION);

            // info
            fail(docData.getInfo() == null, INFO, MISSING_INFO);

        }

        abstract void validate();

        abstract void putErrorMessage();

        abstract void insert();

    }
    
    /**
     * The template method that defines the 
     * skeleton of the upload algorithm.
     * 
     * @param up the Uploader object that defines the specific
     *        behaviour of this algorithm
     * @return true, if the upload was successful, false
     *         otherwise
     */
    protected boolean upload(Uploader up) {

        up.validateFields();
        up.validate();

        if (!getNotification().hasErrors()) {
            up.insert();
            return true;
        }
        up.putErrorMessage();

        return false;
    }
    
    /**
     * Stores a document to the db.
     * 
     * @return true, if the upload was successful, false
     *         otherwise
     */
    public boolean uploadDocument() {
        Uploader doc = new Uploader() {
            void validate() {
                validateDocument();
            }

            void putErrorMessage() {
                getNotification().put(MESSAGE, "Document upload failed.");
            }

            void insert() {
                DocumentDAO docDAO = new DocumentDAO(Registry.getJDBCURL());
                docDAO.insertDocument(docData.getQuakeID(), docData.getDoc(),
                        docData.getDescription(), docData.getInfo());

                docData.getDoc().release();
            }
        };
        return upload(doc);
    }
    
    /**
     * Stores a url to the db.
     * 
     * @return true, if the submission was successful, false
     *         otherwise
     */
    public boolean submitURL() {
        url = validateURL();

        Uploader urlUP = new Uploader() {
            void validate() {
            }

            void putErrorMessage() {
                getNotification().put(MESSAGE, "URL submission failed.");
            }

            void insert() {
                DocumentDAO docDAO = new DocumentDAO(Registry.getJDBCURL());
                docDAO.insertURL(docData.getQuakeID(), url, docData
                        .getDescription(), docData.getInfo());

            }
        };
        return upload(urlUP);

    }

    private URL validateURL() {
        String urlStr = docData.getURL();

        URL url = null;
        try {
            url = new URL(urlStr);
        } catch (MalformedURLException e) {
            getNotification().put(DOCUMENT_URL, MALFORMED_URL);
            return null;
        }

        int sep = url.getPath().lastIndexOf("/");

        if (sep == -1) {
            getNotification().put(DOCUMENT_URL, MALFORMED_URL);
            return null;
        } else {
            return url;
        }

    }

    private void validateDocument() {
        OrdHttpUploadFile doc = docData.getDoc();

        // A document is being uploaded...
        // doc = formData.getFileParameter("doc");

        fail(doc.getContentLength() == 0, DOCUMENT, ZERO_LENGTH_DOC);

        System.out.println("uploaded document size: " + doc.getContentLength());

        failIfNullOrBlank(doc.getOriginalFileName(), DOCUMENT, MISSING_DOC_NAME);
        System.out
                .println("uploaded document name: " + doc.getSimpleFileName());

    }
}